﻿using namespace SocketLib;

#include "socketlibfunction.h"
#include <iostream>
using namespace std;

template<typename SOCKETSTRUCT>
SelectServer<SOCKETSTRUCT>::SelectServer(int num)
{
    m_readSetResult = &(m_socketSet.getReadFDSet());
    m_writeSetResult =&(m_socketSet.getWriteFDSet());

    m_socketPoll.init(num);
    SOCKETSTRUCT* pMemory = m_socketPoll.getMemory();

    for(int i = 0; i < num; ++i)
    {
        _setServer(pMemory[i]);
    }
}

template<typename SOCKETSTRUCT>
int SelectServer<SOCKETSTRUCT>::getClientNum()
{
    return m_connectedSockets.size();
}

template<typename SOCKETSTRUCT>
SOCKETSTRUCT* SelectServer<SOCKETSTRUCT>::getSocketBuffer()
{
    return m_socketPoll.getMemory();
}

template<typename SOCKETSTRUCT>
void SelectServer<SOCKETSTRUCT>::_auxHandlerNewClient(sock clientSocket)
{
    SOCKETSTRUCT* newClient = m_socketPoll.popPtrElement();

    // 判断是否存在可用资源
    if(NULL != newClient)
    {
        _setSocketOnConnected(*newClient, clientSocket);

        m_connectedSockets[clientSocket] = newClient;
        m_socketSet.addSock(clientSocket);

        newClient->onConnection();
    }
    else
    {
        cout << "not have resource, please close socket" << endl;
        SocketLib::SocketApi::CloseSocket(clientSocket);
    }
}

template<typename SOCKETSTRUCT>
void SelectServer<SOCKETSTRUCT>::_handlerCloseList()
{
    if(m_mustCloseList.currentWriteSize() > 0)
    {
        vector<BaseSocket*>& refList = m_mustCloseList.getReadList();

        int closeSize = refList.size();
        if(closeSize > 0)
        {
            for(int i = 0; i < closeSize; ++i)
            {
                SOCKETSTRUCT* p = (SOCKETSTRUCT*)refList[i];
                if(NULL != p)
                {
                    _disConnection(p);
                }
            }

            refList.clear();
        }
    }
}

template<typename SOCKETSTRUCT>
bool SelectServer<SOCKETSTRUCT>::_handlerClientRecv(SOCKETSTRUCT* client)
{
    bool isrecvok = _recvSelectData(*client);
    if(isrecvok)
    {
        client->onRecved();
    }
    else
    {
        client->onClose();
    }

    return isrecvok;
}

template<typename SOCKETSTRUCT>
void SelectServer<SOCKETSTRUCT>::_handlerRecv()
{
#if defined PLATFORM_WINDOWS
    int fdcount = (int)m_readSetResult->fd_count;
    for( int i = 0; i < fdcount; ++i )
    {
        sock fd = m_readSetResult->fd_array[i];
        typename ACTIVELIST::iterator iter = m_connectedSockets.find(fd);

        //TODO::if call _handlerRecv before _handlerSend, so not must check iterator is end
        SOCKETSTRUCT* currentfd = (*iter).second;

        //check read
        if(FD_ISSET(fd, m_readSetResult))
        {
            if(!_handlerClientRecv(currentfd))
            {
                m_socketSet.delSock(fd);
                FD_CLR(fd, m_writeSetResult);    // so in _handlerSend, not must check iterator is end
                m_connectedSockets.erase(iter);
                _setStatus(*currentfd, ESocketHalfClose);
            }
        }
    }
#else

    typename ACTIVELIST::iterator it = m_connectedSockets.begin();
    for(; it != m_connectedSockets.end(); )
    {
        SOCKETSTRUCT*    currentfd = (*it).second;
        sock fd = _getSock(*currentfd);

        if(FD_ISSET(fd, m_readSetResult))
        {
            if(_handlerClientRecv(currentfd))
            {
                ++it;
            }
            else
            {
                m_socketSet.delSock(fd);
                FD_CLR(fd, m_writeSetResult);    // so in _handlerSend, not must check iterator is end
                m_connectedSockets.erase(it++);
                _setStatus(*currentfd, ESocketHalfClose);
            }
        }
        else
        {
            ++it;
        }
    }
#endif
}

template<typename SOCKETSTRUCT>
void SelectServer<SOCKETSTRUCT>::_handlerSend()
{
    #if defined PLATFORM_WINDOWS
    int fdcount = (int)m_writeSetResult->fd_count;

    // if fdcount is big, i will foreach m_socketPoll array

    for( int i = 0; i < fdcount; ++i )
    {
        sock fd = m_writeSetResult->fd_array[i];

        typename ACTIVELIST::iterator iter = m_connectedSockets.find(fd);
        SOCKETSTRUCT*    currentfd = (*iter).second;

        //check write
        if(FD_ISSET(fd, m_writeSetResult))
        {
            if(!_sendSelectData(*currentfd))
            {
                currentfd->onClose();

                m_socketSet.delSock(fd);
                FD_CLR(fd, m_readSetResult);    // so if call _handlerRecv after _handlerSend,  not must check iterator is end in _handlerRecv.

                m_connectedSockets.erase(iter);
                _setStatus(*currentfd, ESocketHalfClose);
            }
        }
    }
    #else
    // if m_connectedSockets.size is big, i will foreach m_socketPoll array

    typename ACTIVELIST::iterator it = m_connectedSockets.begin();
    for(; it != m_connectedSockets.end(); )
    {
        SOCKETSTRUCT* currentfd = (*it).second;
        sock fd = _getSock(*currentfd);
        if(FD_ISSET(fd, m_writeSetResult))
        {
            if(_sendSelectData(*currentfd))
            {
                ++it;
            }
            else
            {
                currentfd->onClose();
                m_socketSet.delSock(fd);

                FD_CLR(fd, m_readSetResult);    // so if call _handlerRecv after _handlerSend,  not must check iterator is end in _handlerRecv.
                m_connectedSockets.erase(it++);
                _setStatus(*currentfd, ESocketHalfClose);
            }
        }
        else
        {
            ++it;
        }
    }
#endif
}

template<typename SOCKETSTRUCT>
void SelectServer<SOCKETSTRUCT>::_handlerAcceptList()
{
    if(m_acceptedList.currentWriteSize() > 0)
    {
        vector<sock>& refList = m_acceptedList.getReadList();
        int num = refList.size();
        if(num > 0)
        {
            for(int i = 0; i < num; ++i)
            {
                _auxHandlerNewClient(refList[i]);
            }

            refList.clear();
        }
    }
}


template<typename SOCKETSTRUCT>
bool SelectServer<SOCKETSTRUCT>::poll(long AOverTime)
{
    _handlerAcceptList();

    int activenum = m_socketSet.poll(AOverTime);

    if(activenum > 0)
    {
        _handlerRecv();
        _handlerSend();
    }
    else if(SOCKET_ERROR == activenum)
    {
        //exit(-1);
        return false;
    }
    _handlerCloseList();

    return true;
}

template<typename SOCKETSTRUCT>
void SelectServer<SOCKETSTRUCT>::_disConnection(SOCKETSTRUCT* AClient)
{
    sock fd = _getSock(*AClient);

    if(fd != SOCKET_ERROR)
    {
        ESocketStatus eStatus = AClient->getStatus();
        if(eStatus == ESocketConnected)
        {
            m_connectedSockets.erase(fd);
            m_socketSet.delSock(fd);
        }

        SocketLib::SocketApi::CloseSocket(fd);

        _initBaseSocket(*AClient);
        m_socketPoll.pushPtrElement(AClient);
    }
}
